package tp.tecnicasdisenio.model.mail;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;

import org.apache.commons.io.FileUtils;

import tp.tecnicasdisenio.dao.impl.jdbc.MensajeDao;
import tp.tecnicasdisenio.model.AutoRespondedorInterface;
import tp.tecnicasdisenio.model.MailInterface;
import tp.tecnicasdisenio.model.ReglaInterface;
import tp.tecnicasdisenio.model.autorespondedor.AutoRespondedor;
import tp.tecnicasdisenio.model.entity.MensajeSMTPMIME;
import tp.tecnicasdisenio.model.factory.ReglaAltaGrupoFactory;
import tp.tecnicasdisenio.model.factory.ReglaAltaMateriaFactory;
import tp.tecnicasdisenio.model.factory.ReglaConsultaTemaPrivadaFactory;
import tp.tecnicasdisenio.model.factory.ReglaConsultaTemaPrivadaResueltaFactory;
import tp.tecnicasdisenio.model.factory.ReglaConsultaTemaPublicaFactory;
import tp.tecnicasdisenio.model.factory.ReglaConsultaTemaPublicaResueltaFactory;
import tp.tecnicasdisenio.model.factory.ReglaEntregaTpFactory;
import tp.tecnicasdisenio.util.LectorPropiedades;

public class MailProcessor {

	public static MailProcessor instance;
	private ReglaInterface primerEslabonDeCadena;
	private AutoRespondedorInterface autoRespondedor;

	private MailProcessor(){
		autoRespondedor= new AutoRespondedor();

		ReglaInterface reglaAltaMateria = ReglaAltaMateriaFactory.getInstance().crear();
		ReglaInterface reglaAltaGrupo = ReglaAltaGrupoFactory.getInstance().crear();
		ReglaInterface reglaEntregaTp = ReglaEntregaTpFactory.getInstance().crear();
		ReglaInterface reglaConsultaTemaPrivada = ReglaConsultaTemaPrivadaFactory.getInstance().crear();
		ReglaInterface reglaConsultaTemaPublica = ReglaConsultaTemaPublicaFactory.getInstance().crear();
		ReglaInterface reglaConsultaTemaPrivadaResuelta = ReglaConsultaTemaPrivadaResueltaFactory.getInstance().crear();
		ReglaInterface reglaConsultaTemaPublicaResuelta = ReglaConsultaTemaPublicaResueltaFactory.getInstance().crear();

		//armo la cadena de responsabilidad
		primerEslabonDeCadena= reglaAltaMateria;
		reglaAltaMateria.siguiente(reglaAltaGrupo);
		reglaAltaGrupo.siguiente(reglaEntregaTp);
		reglaEntregaTp.siguiente(reglaConsultaTemaPrivada);
		reglaConsultaTemaPrivada.siguiente(reglaConsultaTemaPublica);
		reglaConsultaTemaPublica.siguiente(reglaConsultaTemaPrivadaResuelta);
		reglaConsultaTemaPrivadaResuelta.siguiente(reglaConsultaTemaPublicaResuelta);
	}

	public static synchronized MailProcessor getInstance(){
		if(instance == null){
			instance= new MailProcessor();
		}
		return instance;
	}

	public void process(){
		try {
			cargarNuevasReglasDesdeArchivoDeConfiguracion(); 	
		} catch (Exception e) {
			System.err.println("No se puede cargar regla.");
			e.printStackTrace();
		}

		ArrayList<MensajeSMTPMIME> mensajesSMTPMIME= MensajeDao.getInstance().obtenerMensajesNoProcesados(); 
		for(MensajeSMTPMIME unMensaje : mensajesSMTPMIME){
			try {
				System.out.println("Procesando mail con id " + unMensaje.getId());
				unMensaje.setProcesado(true);
				MensajeDao.getInstance().actualizar(unMensaje);
				MailInterface mailInterface= new MailParser(unMensaje);
				primerEslabonDeCadena.aplicarAccionesSobre(mailInterface, autoRespondedor);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}	

	}

	private void agregarEslabonACadena(ReglaInterface eslabon) {
		eslabon.siguiente(primerEslabonDeCadena);
		primerEslabonDeCadena= eslabon;
	}

	private void cargarNuevasReglasDesdeArchivoDeConfiguracion() {
		FileReader grupoFileReader= null;
		BufferedReader grupoBufferedReader= null;
		try {
			File reglaFactoryConfig= new File(LectorPropiedades.getInstance().getPropiedad(LectorPropiedades.RUTA_REGLA_CONFIG));
			grupoFileReader= new FileReader(reglaFactoryConfig);
			grupoBufferedReader =new BufferedReader(grupoFileReader);

			String linea = null;
			while((linea= grupoBufferedReader.readLine()) != null){
				String nombreClase= linea.trim();
				cargarRegla(nombreClase);
			}

			cerrar(grupoFileReader);
			cerrar(grupoBufferedReader);
			
			//FIXME solucion. Limpio archivo
			FileWriter fstream = new FileWriter(reglaFactoryConfig);
			BufferedWriter out = new BufferedWriter(fstream);
			out.write("");
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally{
			try {
				cerrar(grupoFileReader);
				cerrar(grupoBufferedReader);
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}

	private void cerrar(Reader reader) throws IOException{
		if(reader != null){
			reader.close();
		}
	}

	private void cargarRegla(String nombreClase) {
		try {
			Class c= Class.forName(nombreClase);
			ReglaInterface regla= (ReglaInterface)c.newInstance();
			agregarEslabonACadena(regla);
			
			System.out.println("Clase" + c.getName() + " cargada. ");			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
